package com.wut.clock.service.impl;

import com.wut.clock.common.constant.CommentConstant;
import com.wut.clock.common.constant.MessageConstant;
import com.wut.clock.common.util.RedisKeyUtil;
import com.wut.clock.entity.Message;
import com.wut.clock.event.EventProducer;
import com.wut.clock.service.IDislikeService;
import com.wut.clock.util.ShiroUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

/**
 * @Author: yuwei
 * @Date: 2022/6/13 14:36
 * @Description:
 */

@Service
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class DislikeServiceImpl implements IDislikeService {

    private final RedisTemplate redisTemplate;

    private final EventProducer eventProducer;


    @Override
    public void dislike(Integer entityId, Integer entityType, Integer targetUserId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {
                String entityDislikeKey = RedisKeyUtil.getEntityDislikeKey(entityId, entityType);
                String userDislikeKey = RedisKeyUtil.getUserDislikeKey(targetUserId);

                Integer userId = ShiroUtil.getUserId();
                boolean status = getEntityDislikeStatus(entityDislikeKey, userId);

                //开启事务
                redisOperations.multi();
                if (status) { //已经点过踩了，再点则为取消
                    redisOperations.opsForValue().decrement(userDislikeKey);
                    redisOperations.opsForValue().setBit(entityDislikeKey,userId,false);
                }else { //未点过踩
                    redisOperations.opsForValue().setBit(entityDislikeKey,userId,true);
                    redisOperations.opsForValue().increment(userDislikeKey);
                    //发送系统通知
                    Message m = Message.builder()
                            .userId(targetUserId)
                            .fromUserId(userId)
                            .targetId(entityId)
                            .targetType(entityType)
                            .type(MessageConstant.Type.DISLIKE.getCode())
                            .build();
                    eventProducer.fireDislikeEvent(m);
                }
                // 操作对象发生改变，我们使用redis的set集合去判断
                if(entityType.equals(CommentConstant.TopicType.ARTICLE.getCode())){
                    String redisKey = RedisKeyUtil.getArticleScore();
                    redisTemplate.opsForSet().add(redisKey,entityId);
                }
                return redisOperations.exec();
            }
        });
    }

    @Override
    public Long getEntityDislikeCount(Integer entityId, Integer entityType) {
        String entityDislikeKey = RedisKeyUtil.getEntityDislikeKey(entityId, entityType);
        Long size = redisTemplate.opsForValue().size(entityDislikeKey);
        return size == null ? 0 : size;
    }

    @Override
    public Integer getUserDislikeCount(Integer userId) {
        String userDislikeKey = RedisKeyUtil.getUserDislikeKey(userId);
        return (int)redisTemplate.opsForValue().get(userDislikeKey);
    }

    private boolean getEntityDislikeStatus(String entityDislikeKey, Integer userId) {
        Boolean bit = redisTemplate.opsForValue().getBit(entityDislikeKey, userId);
        return bit != null && bit;
    }
}
